package carassius.BLL;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.TreeSet;
import javax.swing.DefaultListModel;
import javax.swing.ListModel;
import javax.swing.event.EventListenerList;

/**
 *
 * @author siebz0r
 */
public class SortedListModel<T>
		extends DefaultListModel
		implements ListModel
{
	private TreeSet<T> _internList;

	public SortedListModel()
	{
		super();
		_internList = new TreeSet<T>();
	}

	@Override
	public int getSize()
	{
		return _internList.size();
	}

	@Override
	public Object getElementAt(int index)
	{
		if (index >= 0 && index < _internList.size())
		{
			Iterator<T> iterator = _internList.iterator();
			for (int i = 0; i < index; i++)
			{
				iterator.next();
			}
			return iterator.next();
		}
		return null;
	}

	@Override
	public void add(int index, Object element)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public void addElement(Object obj)
	{
		int size = _internList.size();
		_internList.add((T) obj);
		fireIntervalAdded(obj, size, size);
	}

	@Override
	public int capacity()
	{
		return _internList.size();
	}

	@Override
	public void clear()
	{
		int size = _internList.size();
		if (size > 0)
		{
			_internList.clear();
			fireIntervalRemoved(this, 0, size-1);
		}
	}

	@Override
	protected Object clone() throws CloneNotSupportedException
	{
		throw new CloneNotSupportedException();
	}

	@Override
	public boolean contains(Object elem)
	{
		return _internList.contains(elem);
	}

	@Override
	public void copyInto(Object[] anArray)
	{
		if (anArray.length < _internList.size())
		{
			anArray = new Object[_internList.size()];
		}
		Iterator iterator = _internList.iterator();
		int i = 0;
		while (iterator.hasNext())
		{
			anArray[i] = iterator.next();
			i++;
		}
	}

	@Override
	public Object elementAt(int index)
	{
		return getElementAt(index);
	}

	@Override
	public Enumeration<T> elements()
	{
		return new Enumeration<T>()
		{
			int i = 0;
			final Object[] array = _internList.toArray();

			@Override
			public boolean hasMoreElements()
			{
				return i < array.length;
			}

			@Override
			public T nextElement()
			{
				T o = (T) array[i];
				i++;
				return o;
			}
		};
	}

	@Override
	public void ensureCapacity(int minCapacity)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	protected void finalize() throws Throwable
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public Object firstElement()
	{
		return _internList.first();
	}

	@Override
	public Object get(int index)
	{
		Object o = getElementAt(index);
		if (o != null)
		{
			return o;
		}
		throw new ArrayIndexOutOfBoundsException();
	}

	@Override
	public int indexOf(Object elem)
	{
		Iterator iterator = _internList.iterator();
		int i = 0;
		while (iterator.hasNext())
		{
			Object o = iterator.next();
			if (o.equals(elem))
			{
				return i;
			}
			i++;
		}
		return -1;
	}

	@Override
	public int indexOf(Object elem, int index)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public void insertElementAt(Object obj, int index)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean isEmpty()
	{
		return _internList.isEmpty();
	}

	@Override
	public Object lastElement()
	{
		return _internList.last();
	}

	@Override
	public int lastIndexOf(Object elem)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public int lastIndexOf(Object elem, int index)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public Object remove(int index)
	{
		Object o = getElementAt(index);
		_internList.remove(o);
		fireIntervalRemoved(this, index, index);
		return o;
	}

	@Override
	public void removeAllElements()
	{
		_internList.clear();
	}

	@Override
	public boolean removeElement(Object obj)
	{
		int index = indexOf(obj);
		if (index > -1 && _internList.remove(obj))
		{
			fireIntervalRemoved(this, index, index);
			return true;
		}
		return false;
	}

	@Override
	public void removeElementAt(int index)
	{
		Object obj = getElementAt(index);
		if (_internList.remove(obj))
		{
			fireIntervalRemoved(this, index, index);
		}
	}

	@Override
	public void removeRange(int fromIndex, int toIndex)
	{
		if (fromIndex >= 0 && fromIndex < _internList.size()
				&& toIndex >= 0 && toIndex < _internList.size())
		{
			ArrayList<Object> removeQueue = new ArrayList<Object>();
			for (int i = fromIndex; i <= toIndex; i++)
			{
				removeQueue.add(getElementAt(i));
			}
			_internList.removeAll(removeQueue);
			fireIntervalRemoved(this, fromIndex, toIndex);
		}
	}

	@Override
	public Object set(int index, Object element)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public void setElementAt(Object obj, int index)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public void setSize(int newSize)
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public int size()
	{
		return _internList.size();
	}

	@Override
	public Object[] toArray()
	{
		return _internList.toArray();
	}

	@Override
	public void trimToSize()
	{
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (getClass() != obj.getClass())
		{
			return false;
		}
		final SortedListModel other = (SortedListModel) obj;
		if (this._internList != other._internList && (this._internList == null || !this._internList.equals(other._internList)))
		{
			return false;
		}
		return super.equals(other);
	}

	@Override
	public int hashCode()
	{
		int hash = 5;
		hash = 59 * hash + (this._internList != null ? this._internList.hashCode() : 0);
		hash = hash + (super.hashCode());
		return hash;
	}

	@Override
	public String toString()
	{
		return _internList.toString();
	}
}
